/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "assetbrowser.h"
#include <assetmodellist.h>
#include <projectmodellist.h>
#include <QtGui/QDropEvent>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>

using namespace Try;

AssetBrowser::AssetBrowser(QWidget* parent)
    :   QDeclarativeView(parent)
{
    this->setObjectName("assetBrowser");
    this->setEnabled(false);

    this->setWindowTitle(tr("Asset Browser"));
    this->setAttribute(Qt::WA_TranslucentBackground, true);
    this->setStyleSheet(QString("background: transparent"));
    this->setResizeMode(QDeclarativeView::SizeRootObjectToView);

    if (parent)
        parent->installEventFilter(this);

    QObject::connect(ProjectModelList::instance(), SIGNAL(projectLoaded(Project*)), this, SLOT(onProjectLoaded(Project*)));
    QObject::connect(ProjectModelList::instance(), SIGNAL(projectClosed(Project*)), this, SLOT(onProjectClosed(Project*)));
    QObject::connect(ProjectModelList::instance(), SIGNAL(projectChanged(Project*)), this, SLOT(onProjectChanged(Project*)));

    QDeclarativeEngine* engine = this->engine();
    QDeclarativeContext* ctxt = engine->rootContext();

    ctxt->setContextProperty("widget", this);
    ctxt->setContextProperty("assets", AssetModelList::instance());

    this->setSource(QUrl("data/ui/AssetBrowser.qml"));
}

AssetBrowser::~AssetBrowser()
{
}

void AssetBrowser::startDraggingAsset(int index)
{
    Asset* asset = AssetModelList::instance()->assetAt(index);

    QString icon = asset->icon();
    if (icon.isEmpty())
        icon = "data/icons/asset.png";

    QMimeData* mimeData = new QMimeData;
    mimeData->setData(asset->type(), asset->name().toUtf8());

    QDrag* drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setPixmap(QPixmap(icon));
    drag->setHotSpot(QPoint(drag->pixmap().width()/2, drag->pixmap().height()));

    drag->exec(Qt::CopyAction);

    emit assetDropped();
}

bool AssetBrowser::eventFilter(QObject* watched, QEvent* evt)
{
    if (watched && ProjectModelList::instance()->rowCount() > 0)
    {
        Project* project = ProjectModelList::instance()->projectAt(0);

        switch (evt->type())
        {
        case QEvent::DragEnter:
        case QEvent::DragLeave:
        case QEvent::DragMove:
            evt->accept();
            return true;

        case QEvent::Drop:
        {
            evt->accept();

            QDropEvent* drop_evt = static_cast<QDropEvent*>(evt);
            if (drop_evt->source() == this)
            {
                const QMimeData* mime = drop_evt->mimeData();

                // Object.
                if (mime->hasFormat("try/object"))
                {
                    QString name = mime->data("try/object");
                    Asset* asset = AssetModelList::instance()->findAssetByName(name);
                    if (asset)
                    {
                        Object* object = asset->create<Try::Object>(project);
                        project->watchObject(object);
                        project->deselectAllObjects();
                        project->selectObject(object);
                    }
                }
            }
        }
        break;

        default:
            break;
        }
    }

    evt->ignore();

    return false;
}

void AssetBrowser::changeEvent(QEvent* evt)
{
    Q_UNUSED(evt)

    emit enabled(this->isEnabled());
}

void AssetBrowser::onProjectChanged(Project* project)
{
    // TODO: a smarter logic.
    this->onProjectLoaded(project);
}

void AssetBrowser::onProjectLoaded(Project* project)
{
    if (project)
        this->setEnabled(true);
}

void AssetBrowser::onProjectClosed(Project* project)
{
    if (project)
        this->setEnabled(false);
}
